# -*- coding: utf-8 -*-
"""
分页处理模块 - 任务2.1
负责网站分页机制的分析和自动翻页功能
"""

import asyncio
import logging
from typing import Dict, Any, List, Optional, Tuple
from playwright.async_api import Page, Locator
import re


class PaginationHandler:
    """分页处理器"""
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.current_page = 1
        self.total_pages = None
        self.pagination_info = {}
    
    async def analyze_pagination(self, page: Page) -> Dict[str, Any]:
        """分析页面的分页机制"""
        try:
            self.logger.info("开始分析分页机制")
            
            pagination_info = {
                'has_pagination': False,
                'pagination_type': None,
                'total_pages': None,
                'current_page': 1,
                'next_button_selector': None,
                'page_number_selectors': [],
                'pagination_container': None
            }
            
            # 等待页面加载完成
            await asyncio.sleep(2)
            
            # 查找分页容器
            pagination_container = await self._find_pagination_container(page)
            if pagination_container:
                pagination_info['pagination_container'] = pagination_container
                pagination_info['has_pagination'] = True
                
                # 分析分页类型和信息
                await self._analyze_pagination_details(page, pagination_info)
            
            self.pagination_info = pagination_info
            self.logger.info(f"分页分析完成: {pagination_info}")
            
            return pagination_info
            
        except Exception as e:
            self.logger.error(f"分页分析失败: {e}")
            return {'has_pagination': False, 'error': str(e)}
    
    async def _find_pagination_container(self, page: Page) -> Optional[str]:
        """查找分页容器"""
        pagination_selectors = [
            '.pagination',
            '.page-nav',
            '.pager',
            '.page-list',
            '[class*="pagination"]',
            '[class*="pager"]',
            '[class*="page"]',
            'nav[aria-label*="分页"]',
            'nav[aria-label*="pagination"]',
            'div:has(button:text-matches("\\d+"))',
            'div:has(a:text-matches("\\d+"))'
        ]
        
        for selector in pagination_selectors:
            try:
                element = page.locator(selector)
                if await element.count() > 0:
                    # 检查是否包含分页相关元素
                    text_content = await element.text_content()
                    if text_content and (
                        re.search(r'\d+', text_content) or 
                        '下一页' in text_content or 
                        '上一页' in text_content or
                        '>' in text_content or
                        '<' in text_content
                    ):
                        self.logger.info(f"找到分页容器: {selector}")
                        return selector
            except Exception:
                continue
        
        return None
    
    async def _analyze_pagination_details(self, page: Page, pagination_info: Dict[str, Any]):
        """分析分页详细信息"""
        try:
            container_selector = pagination_info['pagination_container']
            container = page.locator(container_selector)
            
            # 获取分页容器的文本内容
            container_text = await container.text_content()
            self.logger.debug(f"分页容器内容: {container_text}")
            
            # 查找总页数
            total_pages = await self._extract_total_pages(page, container_text)
            if total_pages:
                pagination_info['total_pages'] = total_pages
            
            # 查找当前页码
            current_page = await self._extract_current_page(page, container_text)
            if current_page:
                pagination_info['current_page'] = current_page
                self.current_page = current_page
            
            # 查找下一页按钮
            next_button_selector = await self._find_next_button(page, container_selector)
            if next_button_selector:
                pagination_info['next_button_selector'] = next_button_selector
                pagination_info['pagination_type'] = 'button'
            
            # 查找页码链接
            page_number_selectors = await self._find_page_numbers(page, container_selector)
            if page_number_selectors:
                pagination_info['page_number_selectors'] = page_number_selectors
                if not pagination_info['pagination_type']:
                    pagination_info['pagination_type'] = 'numbers'
            
            # 检查是否为无限滚动
            if not pagination_info['pagination_type']:
                is_infinite_scroll = await self._check_infinite_scroll(page)
                if is_infinite_scroll:
                    pagination_info['pagination_type'] = 'infinite_scroll'
            
        except Exception as e:
            self.logger.error(f"分析分页详情失败: {e}")
    
    async def _extract_total_pages(self, page: Page, container_text: str) -> Optional[int]:
        """提取总页数"""
        try:
            # 常见的总页数模式
            patterns = [
                r'共\s*(\d+)\s*页',
                r'总共\s*(\d+)\s*页',
                r'/\s*(\d+)',
                r'of\s+(\d+)',
                r'总计\s*(\d+)\s*页'
            ]
            
            for pattern in patterns:
                match = re.search(pattern, container_text)
                if match:
                    total_pages = int(match.group(1))
                    self.logger.info(f"找到总页数: {total_pages}")
                    return total_pages
            
            # 尝试从页码按钮中找到最大页码
            page_numbers = re.findall(r'\b(\d+)\b', container_text)
            if page_numbers:
                max_page = max(int(num) for num in page_numbers if int(num) > 0)
                if max_page > 1:
                    self.logger.info(f"从页码中推断总页数: {max_page}")
                    return max_page
            
        except Exception as e:
            self.logger.error(f"提取总页数失败: {e}")
        
        return None
    
    async def _extract_current_page(self, page: Page, container_text: str) -> Optional[int]:
        """提取当前页码"""
        try:
            # 查找当前页的标识
            current_page_selectors = [
                '.current',
                '.active',
                '.selected',
                '[aria-current="page"]',
                '[class*="current"]',
                '[class*="active"]'
            ]
            
            for selector in current_page_selectors:
                try:
                    element = page.locator(selector)
                    if await element.count() > 0:
                        text = await element.text_content()
                        if text and text.isdigit():
                            current_page = int(text)
                            self.logger.info(f"找到当前页码: {current_page}")
                            return current_page
                except Exception:
                    continue
            
            # 如果没有找到明确的当前页标识，默认为第1页
            return 1
            
        except Exception as e:
            self.logger.error(f"提取当前页码失败: {e}")
            return 1
    
    async def _find_next_button(self, page: Page, container_selector: str) -> Optional[str]:
        """查找下一页按钮"""
        next_button_selectors = [
            f'{container_selector} button:has-text("下一页")',
            f'{container_selector} a:has-text("下一页")',
            f'{container_selector} button:has-text(">")',
            f'{container_selector} a:has-text(">")',
            f'{container_selector} .next',
            f'{container_selector} .page-next',
            f'{container_selector} [aria-label*="下一页"]',
            f'{container_selector} [aria-label*="next"]',
            'button:has-text("下一页")',
            'a:has-text("下一页")',
            'button:has-text(">")',
            'a:has-text(">")'
        ]
        
        for selector in next_button_selectors:
            try:
                element = page.locator(selector)
                if await element.count() > 0:
                    # 检查按钮是否可用
                    is_disabled = await element.get_attribute('disabled')
                    if not is_disabled:
                        self.logger.info(f"找到下一页按钮: {selector}")
                        return selector
            except Exception:
                continue
        
        return None
    
    async def _find_page_numbers(self, page: Page, container_selector: str) -> List[str]:
        """查找页码链接"""
        page_number_selectors = []
        
        number_selectors = [
            f'{container_selector} button:text-matches("\\d+")',
            f'{container_selector} a:text-matches("\\d+")',
            f'{container_selector} span:text-matches("\\d+")'
        ]
        
        for selector in number_selectors:
            try:
                elements = page.locator(selector)
                count = await elements.count()
                if count > 1:  # 至少要有2个页码才算有效
                    page_number_selectors.append(selector)
                    self.logger.info(f"找到页码选择器: {selector} ({count}个)")
            except Exception:
                continue
        
        return page_number_selectors
    
    async def _check_infinite_scroll(self, page: Page) -> bool:
        """检查是否为无限滚动"""
        try:
            # 记录当前页面高度
            initial_height = await page.evaluate("document.body.scrollHeight")
            
            # 滚动到页面底部
            await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
            await asyncio.sleep(2)
            
            # 检查页面高度是否发生变化
            new_height = await page.evaluate("document.body.scrollHeight")
            
            if new_height > initial_height:
                self.logger.info("检测到无限滚动")
                return True
            
        except Exception as e:
            self.logger.error(f"检查无限滚动失败: {e}")
        
        return False
    
    async def go_to_next_page(self, page: Page) -> bool:
        """翻到下一页"""
        try:
            if not self.pagination_info.get('has_pagination'):
                self.logger.warning("没有分页信息，无法翻页")
                return False
            
            pagination_type = self.pagination_info.get('pagination_type')
            
            if pagination_type == 'button':
                return await self._click_next_button(page)
            elif pagination_type == 'numbers':
                return await self._click_next_page_number(page)
            elif pagination_type == 'infinite_scroll':
                return await self._handle_infinite_scroll(page)
            else:
                self.logger.warning(f"未知的分页类型: {pagination_type}")
                return False
                
        except Exception as e:
            self.logger.error(f"翻页失败: {e}")
            return False
    
    async def _click_next_button(self, page: Page) -> bool:
        """点击下一页按钮"""
        try:
            next_button_selector = self.pagination_info.get('next_button_selector')
            if not next_button_selector:
                return False
            
            next_button = page.locator(next_button_selector)
            if await next_button.count() > 0:
                # 检查按钮是否可用
                is_disabled = await next_button.get_attribute('disabled')
                if not is_disabled:
                    await next_button.click()
                    await page.wait_for_load_state('networkidle', timeout=30000)
                    self.current_page += 1
                    self.logger.info(f"成功翻到第 {self.current_page} 页")
                    return True
                else:
                    self.logger.info("下一页按钮已禁用，已到最后一页")
                    return False
            
        except Exception as e:
            self.logger.error(f"点击下一页按钮失败: {e}")
        
        return False
    
    async def _click_next_page_number(self, page: Page) -> bool:
        """点击下一页页码"""
        try:
            page_number_selectors = self.pagination_info.get('page_number_selectors', [])
            
            for selector in page_number_selectors:
                try:
                    # 查找下一页的页码
                    next_page_num = self.current_page + 1
                    next_page_element = page.locator(f'{selector}:has-text("{next_page_num}")')
                    
                    if await next_page_element.count() > 0:
                        await next_page_element.click()
                        await page.wait_for_load_state('networkidle', timeout=30000)
                        self.current_page = next_page_num
                        self.logger.info(f"成功翻到第 {self.current_page} 页")
                        return True
                        
                except Exception:
                    continue
            
            self.logger.info("没有找到下一页页码，可能已到最后一页")
            return False
            
        except Exception as e:
            self.logger.error(f"点击页码失败: {e}")
            return False
    
    async def _handle_infinite_scroll(self, page: Page) -> bool:
        """处理无限滚动"""
        try:
            # 记录当前页面高度
            initial_height = await page.evaluate("document.body.scrollHeight")
            
            # 滚动到页面底部
            await page.evaluate("window.scrollTo(0, document.body.scrollHeight)")
            await asyncio.sleep(3)  # 等待新内容加载
            
            # 检查页面高度是否发生变化
            new_height = await page.evaluate("document.body.scrollHeight")
            
            if new_height > initial_height:
                self.logger.info("无限滚动加载了新内容")
                return True
            else:
                self.logger.info("无限滚动已到底部")
                return False
                
        except Exception as e:
            self.logger.error(f"处理无限滚动失败: {e}")
            return False
    
    def get_pagination_status(self) -> Dict[str, Any]:
        """获取分页状态"""
        return {
            'current_page': self.current_page,
            'total_pages': self.total_pages,
            'has_pagination': self.pagination_info.get('has_pagination', False),
            'pagination_type': self.pagination_info.get('pagination_type'),
            'pagination_info': self.pagination_info
        }
    
    def reset_pagination_state(self):
        """重置分页状态"""
        self.current_page = 1
        self.total_pages = None
        self.pagination_info = {}
        self.logger.info("分页状态已重置")
